/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is Forte for Java, Community Edition. The Initial * Developer of the Original Code is Sun Microsystems, Inc. Portions * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved. */ package org.netbeans.core.execution; import java.io.InputStream; import java.io.PrintStream; import java.util.Hashtable; import org.openide.TopManager; import org.openide.windows.InputOutput; import org.openide.windows.OutputWriter; import org.openide.windows.TopComponent; /** Tasks are supposed to obey following model: every task is a ThreadGroup * and the ThreadGroup is under another ThreadGroup - called "base". * Systems threads are not under group base. * The table keeps couples ThreadGroup:TaskIO; each task is supposed * to be encapsulate by a ThreadGroup; system's threads have special * handling @see #systemIO * Some tasks don't require io operations. For such tasks NullTaskIO is * created (at ExecutionEngine.RunClass.run()); NullTaskIOs left reusing TaskIOs * * * @author Ales Novak */ final class IOTable extends Hashtable { /** generated Serialized Version UID */ static final long serialVersionUID = 9096333712401558521L; /** ThreadGroup of all tasks */ private ThreadGroup base; /** TaskIO of system's threads */ private TaskIO systemIO; /** hashtable of free TaskIOs - name:TaskIO * @associates TaskIO*/ private Hashtable freeTaskIOs; /** our options */ private ExecutionSettings options; /** * @param base is a base ThreadGroup for tasks * @param systemIO is a TaskIO instance that is used for system threads */ public IOTable(ThreadGroup base, TaskIO systemIO) { this.base = base; this.systemIO = systemIO; freeTaskIOs = new Hashtable(17); options = new ExecutionSettings(); } /** finds top thread group of the calling thread * @return null iff the calling thread is not in any exec group * or exec group of calling thread */ ThreadGroup findGroup () { ThreadGroup g = Thread.currentThread().getThreadGroup (); ThreadGroup old = null; while (g != null && g != base) { old = g; g = g.getParent (); } return (g == null) ? null : old; } /** * @return TaskIO specific for calling thread/threadgroup */ private synchronized TaskIO getIO() { InputOutput inout = null; if (Thread.currentThread() instanceof IOThreadIfc) { inout = ((IOThreadIfc) Thread.currentThread()).getInputOutput(); } IOPermissionCollection iopc = null; if (inout == null) { iopc = AccController.getIOPermissionCollection(); if (iopc == null) { return systemIO; } inout = iopc.getIO(); } TaskIO io = (TaskIO) get(inout); // this piece of source is duplicated in exec engine // needed when classloader defines a class with an InpuOutput // but the classloader does not work on behalf of execution // following code is executed only if a task is dead but // some classes behave like Phoenix - they live again if (io == null) { if (inout instanceof TopComponent) { String allName = ((TopComponent) inout).getName(); io = getTaskIO(allName); if (io == null) { // executed for the first time inout = TopManager.getDefault().getIO(allName); io = new TaskIO(inout, allName); } else { inout = io.getInout(); } inout.select(); inout.setFocusTaken(true); if ( iopc!= null) { // IOThreadIfc case iopc.setIO(inout); } put(inout, io); } else { return new TaskIO(inout); // foreign inout - just return a TaskIO } } return io; } /** * @param name is a name of the tab * @return TaskIO */ synchronized TaskIO getTaskIO(String name) { TaskIO ret; if (reuseTaskIO()) if ((ret = getFreeTaskIO(name)) != null) return ret; return null; } /** * @return true iff TaskIO are to be reused */ private boolean reuseTaskIO() { return options.getReuse(); } /** * @return true iff reused TaskIO should be reseted */ private boolean clearTaskIO() { return options.getClear(); } /** * @return free non-used TaskIO with given name or null */ private TaskIO getFreeTaskIO(String name) { TaskIO t = (TaskIO) freeTaskIOs.get(name); if (t == null) { return null; } if (clearTaskIO()) { try { t.getInout().getOut().reset(); t.getInout().getErr().reset(); } catch (java.io.IOException e) { } } t.in = null; t.getInout().flushReader(); freeTaskIOs.remove(name); return t; } /** frees resources binded to grp * @param grp is a ThreadGroup which TaskIO is to be released * @param io key for freed TaskIO */ synchronized void free(ThreadGroup grp, InputOutput io) { TaskIO t = (TaskIO) get(io); if (t == null) { return; // nothing ?? } else if (t.foreign) { return; } if ((t != TaskIO.Null) && (t.getName() != TaskIO.VOID)) { // Null t = (TaskIO) freeTaskIOs.put(t.getName(), t); // free it if (t != null) { t.getInout().closeInputOutput(); // old one destroy } } remove(io); } /** * @return threadgroup specific input stream */ public InputStream getIn () { TaskIO io = getIO (); if (io.in == null) io.initIn (); return io.in; } /** * @return thread specific PrintStream * Two calls in the same threadgroup will return the same PrintStream */ public PrintStream getOut () { TaskIO io = getIO (); if (io.out == null) io.initOut (); return io.out; } /** * @return thread specific PrintStream * Two calls in the same threadgroup will return the same PrintStream */ public PrintStream getErr () { TaskIO io = getIO (); if (io.err == null) io.initErr (); return io.err; } } /* * Log * 19 Gandalf 1.18 1/12/00 Ales Novak i18n * 18 Gandalf 1.17 1/11/00 Ales Novak provided InputOutput is * not handled by execution system * 17 Gandalf 1.16 10/22/99 Ian Formanek NO SEMANTIC CHANGE - Sun * Microsystems Copyright in File Comment * 16 Gandalf 1.15 10/8/99 Ales Novak improved redirection of * IO operations * 15 Gandalf 1.14 10/4/99 Jaroslav Tulach SysProcess deleted. * 14 Gandalf 1.13 10/1/99 Ales Novak major change of * execution * 13 Gandalf 1.12 7/28/99 Ales Novak new window system/#1409 * 12 Gandalf 1.11 6/28/99 Ian Formanek Removed obsoleted * imports * 11 Gandalf 1.10 6/8/99 Ian Formanek ---- Package Change To * org.openide ---- * 10 Gandalf 1.9 5/13/99 Ales Novak bugfix #1453 * 9 Gandalf 1.8 5/13/99 Ales Novak bugfix #1453 * 8 Gandalf 1.7 4/9/99 Ales Novak * 7 Gandalf 1.6 4/8/99 Ales Novak * 6 Gandalf 1.5 4/2/99 Ales Novak * 5 Gandalf 1.4 3/31/99 Ales Novak * 4 Gandalf 1.3 3/24/99 Ales Novak * 3 Gandalf 1.2 1/21/99 Ales Novak * 2 Gandalf 1.1 1/8/99 Ales Novak * 1 Gandalf 1.0 1/5/99 Ian Formanek * $ * Beta Change History: * 0 Tuborg 0.11 --/--/98 Jan Jancura tab switching changed * 0 Tuborg 0.12 --/--/98 Ales Novak termination of processes at menu added * 0 Tuborg 0.14 --/--/98 Jan Formanek changed order of terminate and close in context menu * 0 Tuborg 0.14 --/--/98 Jan Formanek terminate disabled if the process is not running */